package com.example.wenmini.service;

import com.example.wenmini.config.ProxyConfig;
import com.example.wenmini.entity.Proxy;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.GZIPInputStream;

@Slf4j
@Service
public class ProxyService {

    @Autowired
    private ProxyConfig proxyConfig;

    
    private final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 获取代理信息
     * @return Proxy对象，包含IP和端口信息
     */
    public Proxy getProxy() {
        try {
            String apiResponse = fetchProxyFromApi();
            if (apiResponse == null) {
                log.error("无法从API获取代理");
                return null;
            }
            
            Proxy proxy = parseProxyResponse(apiResponse);
            if (proxy == null) {
                log.error("解析代理响应失败");
                return null;
            }
            
            // 验证代理是否可用
            if (!verifyProxy(proxy)) {
                log.error("代理验证失败：{}:{}", proxy.getIp(), proxy.getPort());
                return null;
            }
            
            return proxy;
        } catch (Exception e) {
            log.error("获取代理失败：{}", e.getMessage());
            return null;
        }
    }
    
    /**
     * 从API获取代理
     */
    private String fetchProxyFromApi() {
        try {
            String apiUrl = "";    // 这里填写API地址
            if (apiUrl == null) {
                log.error("代理API URL未配置");
                return null;
            }

            log.info("开始请求代理API，URL: {}", apiUrl);
            
            URL url = new URL(apiUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(5000);
            
            int responseCode = conn.getResponseCode();
            log.info("代理API响应码: {}", responseCode);
            
            if (responseCode != HttpURLConnection.HTTP_OK) {
                log.error("代理API请求失败，响应码: {}", responseCode);
                return null;
            }
            
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
                String response = reader.readLine();
                log.info("成功获取代理响应: {}", response);
                return response;
            }
        } catch (Exception e) {
            log.error("请求代理API失败：{}", e.getMessage());
            return null;
        }
    }
    
    /**
     * 解析代理响应
     */
    private Proxy parseProxyResponse(String response) {
        try {
            // 首先尝试解析为JSON格式
            try {
                return parseJsonResponse(response);
            } catch (Exception e) {
                log.info("JSON解析失败，尝试解析直接返回的IP:PORT格式");
                return parseDirectIpPortResponse(response);
            }
        } catch (Exception e) {
            log.error("解析代理响应失败：{}", e.getMessage());
            return null;
        }
    }
    
    /**
     * 解析JSON格式的代理响应
     */
    private Proxy parseJsonResponse(String response) throws JsonProcessingException {
        JsonNode jsonNode = objectMapper.readTree(response);
        
        // 检查响应码
        if (!"0".equals(jsonNode.path("code").asText())) {
            log.error("代理API返回错误：{}", jsonNode.path("msg").asText());
            return null;
        }
        
        // 获取代理信息
        JsonNode obj = jsonNode.path("obj").get(0);
        if (obj == null) {
            log.error("代理信息为空");
            return null;
        }
        
        String ip = obj.path("ip").asText();
        String port = obj.path("port").asText();
        
        if (ip.isEmpty() || port.isEmpty()) {
            log.error("代理IP或端口为空");
            return null;
        }
        
        return createProxy(ip, Integer.parseInt(port));
    }
    
    /**
     * 解析直接返回的IP:PORT格式
     */
    private Proxy parseDirectIpPortResponse(String response) {
        response = response.trim();
        
        // 验证响应格式
        if (!response.matches("^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}:\\d{1,5}$")) {
            throw new IllegalArgumentException("响应格式不是有效的IP:PORT格式");
        }
        
        String[] parts = response.split(":");
        if (parts.length != 2) {
            throw new IllegalArgumentException("无法解析IP和端口");
        }
        
        String ip = parts[0];
        int port = Integer.parseInt(parts[1]);
        
        // 验证IP格式
        if (!isValidIp(ip)) {
            throw new IllegalArgumentException("无效的IP地址格式");
        }
        
        // 验证端口范围
        if (port <= 0 || port > 65535) {
            throw new IllegalArgumentException("无效的端口号");
        }
        
        return createProxy(ip, port);
    }
    
    /**
     * 验证IP地址格式
     */
    private boolean isValidIp(String ip) {
        try {
            String[] parts = ip.split("\\.");
            if (parts.length != 4) {
                return false;
            }
            
            for (String part : parts) {
                int value = Integer.parseInt(part);
                if (value < 0 || value > 255) {
                    return false;
                }
            }
            
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }
    
    /**
     * 创建代理对象
     */
    private Proxy createProxy(String ip, int port) {
        Proxy proxy = new Proxy();
        proxy.setIp(ip);
        proxy.setPort(port);
        proxy.setCreateTime(LocalDateTime.now());
        proxy.setLastCheckTime(LocalDateTime.now());
        proxy.setStatus(1); // 1表示可用
        
        log.info("成功解析代理信息：{}:{}", ip, port);
        return proxy;
    }
    
    /**
     * 验证代理是否可用
     */
    private boolean verifyProxy(Proxy proxy) {
        String proxyAddress = String.format("%s:%d", proxy.getIp(), proxy.getPort());
        log.info("开始验证代理：{}", proxyAddress);

        for (String testUrl : proxyConfig.getWarmupTestUrls()) {
            HttpURLConnection conn = null;
            try {
                URL url = new URL(testUrl);
                java.net.Proxy javaProxy = new java.net.Proxy(java.net.Proxy.Type.HTTP, 
                    new InetSocketAddress(proxy.getIp(), proxy.getPort()));
                
                conn = (HttpURLConnection) url.openConnection(javaProxy);
                conn.setRequestMethod("GET");
                conn.setConnectTimeout(10000);
                conn.setReadTimeout(10000);
                conn.setInstanceFollowRedirects(true);
                
                // 设置请求头
                Map<String, String> headers = new HashMap<>();
                headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36");
                headers.put("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8");
                headers.put("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8");
                headers.put("Accept-Encoding", "gzip, deflate, br");
                headers.put("Connection", "keep-alive");
                headers.put("Cache-Control", "no-cache");
                headers.put("Pragma", "no-cache");
                headers.put("Upgrade-Insecure-Requests", "1");
                headers.put("sec-ch-ua", "\"Not_A Brand\";v=\"8\", \"Chromium\";v=\"120\"");
                headers.put("sec-ch-ua-mobile", "?0");
                headers.put("sec-ch-ua-platform", "\"Windows\"");
                
                // 应用所有请求头
                headers.forEach(conn::setRequestProperty);
                
                // 发送请求并获取响应码
                int responseCode = conn.getResponseCode();
                log.info("代理{}访问{}的响应码: {}", proxyAddress, testUrl, responseCode);
                
                // 处理重定向
                if (responseCode == HttpURLConnection.HTTP_MOVED_TEMP || 
                    responseCode == HttpURLConnection.HTTP_MOVED_PERM || 
                    responseCode == HttpURLConnection.HTTP_SEE_OTHER) {
                    
                    String newUrl = conn.getHeaderField("Location");
                    log.info("请求被重定向到: {}", newUrl);
                    
                    // 关闭旧连接
                    conn.disconnect();
                    
                    // 创建新连接
                    url = new URL(newUrl);
                    conn = (HttpURLConnection) url.openConnection(javaProxy);
                    headers.forEach(conn::setRequestProperty);
                    responseCode = conn.getResponseCode();
                }
                
                if (responseCode != HttpURLConnection.HTTP_OK) {
                    log.error("代理{}访问{}失败，响应码: {}", proxyAddress, testUrl, responseCode);
                    return false;
                }
                
                // 获取响应内容
                String contentType = conn.getContentType();
                String charset = getCharset(contentType);
                
                // 读取响应内容
                StringBuilder content = new StringBuilder();
                try (InputStream inputStream = conn.getInputStream();
                     BufferedReader reader = new BufferedReader(new InputStreamReader(
                         "gzip".equalsIgnoreCase(conn.getContentEncoding()) 
                             ? new GZIPInputStream(inputStream) 
                             : inputStream, 
                         charset))) {
                    
                    String line;
                    while ((line = reader.readLine()) != null) {
                        content.append(line).append("\n");
                    }
                }
                
                String responseContent = content.toString();
                int contentLength = responseContent.length();
                log.info("响应内容长度: {} 字节", contentLength);
                
                // 验证响应内容
                if (contentLength < 1000) { // 内容太短可能是错误页面
                    log.error("响应内容过短，可能是错误页面");
                    return false;
                }
                
                // 检查是否包含问卷星特征
                boolean hasWjxFeature = responseContent.contains("问卷星") || 
                                      responseContent.contains("wjx.cn") ||
                                      responseContent.contains("问卷调查") ||
                                      responseContent.contains("questionnaire");
                                      
                if (!hasWjxFeature) {
                    log.error("响应内容不包含问卷星特征");
                    return false;
                }
                
                log.info("代理{}成功访问：{}", proxyAddress, testUrl);
                return true;
                
            } catch (Exception e) {
                log.error("代理{}验证失败：{}", proxyAddress, e.getMessage());
                return false;
            } finally {
                if (conn != null) {
                    conn.disconnect();
                }
            }
        }
        
        return false;
    }
    
    /**
     * 从Content-Type中获取字符集
     */
    private String getCharset(String contentType) {
        if (contentType != null) {
            String[] values = contentType.split(";");
            for (String value : values) {
                value = value.trim();
                if (value.toLowerCase().startsWith("charset=")) {
                    return value.substring("charset=".length());
                }
            }
        }
        return "UTF-8"; // 默认使用UTF-8
    }
}